
表面着色器实际上就是在顶点/片元着色器之上又添加了一层抽象; 表面着色器最终会被编译为一个复杂的顶点着色程序
编译指令最重要的作用是指明该表面着色器使用的表面函数和光照函数,并设置一些可选参数
#pragma surface surfaceFunction lightModel [optionalparams]表面着色器包含 4 个函数
surface 后面跟表面着色器的入口函数 surf(Input IN, inout SurfaceOutput o);
光照模型
<Name>(SurfaceOutput s, half3 lightDir, half aten); // 用于不依赖视角的光照模型,漫反射<Name>(SurfaceOutput s, half3 lightDir, half3 viewDir, half aten); // 用于不依赖视角的光照模型,高光反射<Name>(SurfaceOutput s, half4 light);可选参数 vertex:VertexFunction 顶点修改函数
<Name>(inout appdata_full v) 只需要改顶点着色器中的输入顶点数据<Name>(inout appdata_full v, out Input o) 修改输入顶点数据,以及为表面着色器传递数据可选参数 finalcolor:ColorFunction 最终颜色修改函数
<Name>(Input IN, SurfaceOutput o, inout fixed4 color)其他可选参数 1: alpha:Alpha 混合模式,用户半透明着色器; 2: alphatest:varirableName Alpha 测试模式,用户透明镂空着色器 3: exclude_path:prepass 使用指定的渲染路径 3: exclude_path:deferred 使用指定的渲染路径 缩小自动生成的代码量 4: addshadow: 添加阴影投射器和集合通道; 5: dualforward:将双重光照贴图用于正向渲染路径中; 6: fullforwardshadows 在正想渲染路径中支持的所有的阴影类型 7: decal:add 附加印花着色器: 8: decal:blend 附加半透明印花着色器:9: softvegetation 使用表面着色器,仅在 Soft Vegetation 开启时被渲染;10:noambient 不使用任何光照 11: novertexlights 在正向渲染中不适用球面调和光照或逐点光照 12: nolightmap 在这个着色器上禁用光照贴图: 13: nodirlightmap 在这个着色器上禁用方向光照贴图 14: noforwardadd 禁用正向渲染添加通道: 15: approxview: 对于有需要的着色器,逐顶点而不是逐像素计算规范化视线方向 16: halfasview: 将半方向传递到光照函数中。 17: nometa 取消对提取元数据Pass的生成
表面函数的输入结构体Input,以及存储了表面属性的结构体SurfaceOutput (SurfaceOutputStandard\SurfaceOutputStandardSpecular)
Input 必须包含着色器所需要的纹理坐标 uv + 纹理名字;如果使用第二张纹理 uv2 + 纹理名字
Input 结构体包含了许多表面属性的数据来源,他会作为表面函数的输入结构体
一个例外的情况是,我们自定义了顶点修改函数,并需要像表面函数中传入一些自定义的数据,例如,自定义的雾效,我们可能需要在顶点修改函数中根据顶点在视角空间下的位置信息计算雾效混合系数,这样我们就可以在Input结构体中定义一个名为half fog的变量,把计算结果存储在该变量后进行输出
如果使用了非基于物理的光照模型,我们通常会使用SurfaceOutput结构体;而如果使用了基于物理的光照模型Standard或StandardSpecular,我们会分别使用SurfaceOutputStandard或SurfaceOutputStandardSpecular
SurfaceOutput
SurfaceOutputStandard
SurfaceOutputStandardSpecular